﻿'----------------------------------------------------------------------
' Created with SharpDevelop
' Author: Adam Yarnott, Blue Ninja Software
' Copyright (c) Adam Yarnott, Blue Ninja Software.
' Date: 8/22/2007
' Time: 9:00 AM
'----------------------------------------------------------------------

Imports System.Runtime.InteropServices

Namespace Reports
	
	''' <summary>
	''' The ReportTypeEnum enumeration type is used to specify an HID report type.
	''' </summary>
	Public Enum ReportTypeEnum As Integer
		''' <summary>Indicates an input report.</summary>
		Input = Interop.HID.HIDP_REPORT_TYPE.Input
		
		''' <summary>Indicates an output report.</summary>
		Output = Interop.HID.HIDP_REPORT_TYPE.Output
		
		''' <summary>Indicates a feature report.</summary>
		Feature = Interop.HID.HIDP_REPORT_TYPE.Feature
	End Enum
	
	''' <summary>
	''' Abstract base class for all HID reports.
	''' </summary>
	Public MustInherit Class AHIDReport
		Implements IEquatable(Of AHIDReport)
		
		#Region "Private Members"
		
		Private _ReportLength As UShort
		
		Private _Buffer As Byte()
		
		#End Region
		
		#Region "Constructors"
		
		Protected Sub New(ByVal ReportLength As UShort)
            _ReportLength = ReportLength
			
            ReDim _Buffer(ReportLength - 1)
		End Sub
		
		Protected Sub New(ByVal ReportLength As UShort, ByVal ReportID As Byte)
			_ReportLength = ReportLength
			
            ReDim _Buffer(ReportLength - 1)
			
			_Buffer(0) = ReportID
		End Sub
		
		Protected Sub New(ByVal ReportLength As UShort, ByVal ReportID As Byte, ByVal ReportData As Byte())
			_ReportLength = ReportLength
			
            ReDim _Buffer(ReportLength - 1)
			
			_Buffer(0) = ReportID
			
            If ReportData.Length = _ReportLength - 1 Then
                Array.Copy(ReportData, 0, _Buffer, 1, ReportData.Length)
            Else
                Throw New ArgumentException("Report data size too large.")
            End If
		End Sub
		
        Protected Sub New(ByVal ReportBuffer As Byte())
            'First byte is ReportId
            _ReportLength = ReportBuffer.Length
            _Buffer = ReportBuffer.Clone
        End Sub
		
		#End Region
		
		#Region "Public Properties"
		
		''' <summary>
		''' Gets or sets the Report ID (first byte of raw buffer).
		''' </summary>
		Public Overridable Property ReportID() As Byte
			Get
				Return _Buffer(0)
			End Get
			Set
				_Buffer(0) = value
			End Set
		End Property
		
		''' <summary>
		''' Returns the length of the report: ReportData.Length + 1 for the ReportID.
		''' </summary>
		Public ReadOnly Property ReportLength As UShort
			Get
                Return _ReportLength - 1
			End Get
		End Property
		
        ''' <summary>
        ''' Gets or sets the ReportData as a byte array.
        ''' </summary>
        Public Overridable Property ReportDataArray() As Byte()
            Get
                Dim Buff(ReportLength - 1) As Byte

                Array.Copy(_Buffer, 1, Buff, 0, ReportLength)

                Return Buff
            End Get
            Set(ByVal value As Byte())
                If value.Length > ReportLength Then
                    Throw New InvalidOperationException("Invalid length.")
                Else
                    Array.Copy(value, 0, _Buffer, 1, value.Length)
                End If
            End Set
        End Property

        ''' <summary>
        ''' Gets or sets the value of the specified byte of the ReportData buffer.
        ''' </summary>
        Public Overridable Property ReportData(ByVal Index As UShort) As Byte
            Get
                If Index > _ReportLength - 2 Then
                    Throw New InvalidOperationException("Index falls outside of valid range.")
                Else
                    Return _Buffer(Index + 1)
                End If
            End Get
            Set(ByVal value As Byte)
                If Index > _ReportLength - 2 Then
                    Throw New InvalidOperationException("Index falls outside of valid range.")
                Else
                    _Buffer(Index + 1) = value
                End If
            End Set
        End Property

#End Region

#Region "Public Methods"

        ''' <summary>
        ''' Returns the raw buffer as a byte array.
        ''' </summary>
        ''' <returns></returns>
        Public Function GetBuffer() As Byte()
            Return _Buffer
        End Function

#End Region

#Region "Override Methods"

        Public Overloads Overrides Function ToString() As String
            Return String.Format("Report ID: {0}, Data: {1}", PadHex(Hex(Me.ReportID), 2), BitConverter.ToString(Me.ReportDataArray))
        End Function

#End Region

#Region "IEquatable Support"

        Public Overloads Function Equals(other As AHIDReport) As Boolean Implements IEquatable(Of AHIDReport).Equals
            If other IsNot Nothing AndAlso _Buffer.Length = other._Buffer.Length Then
                For i As Integer = 0 To _Buffer.Length - 1
                    If _Buffer(i) <> other._Buffer(i) Then
                        'Different data, reports not the same.
                        Return False
                    End If
                Next

                'If we got here, reports are identical.
                Return True
            Else
                'Different lengths, reports not the same.
                Return False
            End If
        End Function

        Public Overloads Overrides Function Equals(obj As Object) As Boolean
            If Not (TypeOf obj Is AHIDReport) Then
                Return False
            Else
                Return Me.Equals(DirectCast(obj, AHIDReport))
            End If
        End Function

#End Region

    End Class
	
End Namespace
